package com.work.demo.utils;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;

/**
 * @ClassName : TestUtil
 * @Description :
 * @Author : LinYa
 * @Date: 2022/5/28  9:21
 */
public class TestUtil {


	private static final byte[] SECRET_KEY_BYTE = {88, -91, -8, -75, 63, -16, 16, -90, 46, -78, -23, -125, 3, -9, -46, -48};
	private static final SecretKey SECRET_KEY = new SecretKeySpec(SECRET_KEY_BYTE, "AES");

	private static final byte[] OFFSET_IV = {-120, -77, 95, -88, -73, 88, 121, 119, 119, -37, -81, -88, 29, -13, -68, -97};

	private static final String CIPHER_TYPE = "AES/GCM/NoPadding";

	static {
		Security.addProvider(new BouncyCastleProvider());
	}

	public static byte[] encrypt(byte[] data) {
		try {
			Cipher cipher = Cipher.getInstance(CIPHER_TYPE);

			AlgorithmParameterSpec parameterSpec = new GCMParameterSpec(128, OFFSET_IV); //128 bit auth tag length
			cipher.init(Cipher.ENCRYPT_MODE, SECRET_KEY, parameterSpec);

			byte[] cipherText = cipher.doFinal(data);
			ByteBuffer byteBuffer = ByteBuffer.allocate(OFFSET_IV.length + cipherText.length);
			byteBuffer.put(OFFSET_IV);
			byteBuffer.put(cipherText);
			return byteBuffer.array();
		} catch (NoSuchAlgorithmException
						| NoSuchPaddingException
						| InvalidKeyException
						| InvalidAlgorithmParameterException
						| IllegalBlockSizeException
						| BadPaddingException ignored) {
		}
		return null;
	}

	public static String decrypt(byte[] cipherMessage) {
		try {
			final Cipher cipher = Cipher.getInstance(CIPHER_TYPE);
			AlgorithmParameterSpec gcmIv = new GCMParameterSpec(128, cipherMessage, 0, OFFSET_IV.length);
			cipher.init(Cipher.DECRYPT_MODE, SECRET_KEY, gcmIv);
			byte[] plainText = cipher.doFinal(cipherMessage, OFFSET_IV.length, cipherMessage.length - OFFSET_IV.length);
			return new String(plainText, StandardCharsets.UTF_8);

		} catch (Exception e) {
			e.getStackTrace();
		}
		return null;
	}
}
